package com.fy.fyspace.controller;

import com.fy.fyspace.common.annotation.GlobalInterceptor;
import com.fy.fyspace.common.result.R;
import com.fy.fyspace.ex.handler.ExHandler;
import com.fy.fyspace.model.dto.hotness.HotnessRankingQueryDTO;
import com.fy.fyspace.model.vo.hotness.HotnessRankingVO;
import com.fy.fyspace.service.HotnessRankingCacheService;
import com.fy.fyspace.service.PictureHotnessService;
import com.fy.fyspace.service.hotness.strategy.HotnessStrategyFactory;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.stream.Collectors;

import static com.fy.fyspace.common.result.R.no;
import static com.fy.fyspace.common.result.R.ok;

/**
 * 热度管理控制器
 * 设计模式：控制器模式
 * 作用：提供热度计算和排行榜查询的REST API接口
 */
@Api(tags = "热度管理接口")
@Slf4j
@RestController
@RequestMapping("/hotness")
public class HotnessController extends BaseController {
    
    @Autowired
    private PictureHotnessService pictureHotnessService;
    
    @Autowired
    private HotnessRankingCacheService rankingCacheService;
    
    @Autowired
    private HotnessStrategyFactory strategyFactory;
    
    @PostMapping("/calculate/all")
    @ApiOperation(value = "重新计算所有图片热度", notes = "管理员手动触发全量热度重新计算")
    @ApiResponses({
        @ApiResponse(code = 200, message = "计算成功"),
        @ApiResponse(code = 400, message = "计算失败")
    })
    @GlobalInterceptor(checkAdmin = true)
    public R<String> calculateAllHotness(
            @RequestParam(defaultValue = "standardHotnessStrategy") String strategyName) {
        
        try {
            log.info("管理员触发全量热度重新计算，策略: {}", strategyName);
            
            // 计算所有图片的热度
            var hotnessList = pictureHotnessService.calculateAllHotness(strategyName);
            
            log.info("全量热度计算完成，成功计算数量: {}", hotnessList.size());
            return ok("全量热度计算完成，成功计算 " + hotnessList.size() + " 张图片");
            
        } catch (Exception e) {
            log.error("全量热度计算失败", e);
            return no("全量计算失败：" + e.getMessage());
        }
    }
    
    @PostMapping("/historical/update/all")
    @ApiOperation(value = "更新所有图片历史分数", notes = "管理员手动触发更新所有图片的历史分数（昨日、上周、上月）")
    @ApiResponses({
        @ApiResponse(code = 200, message = "更新成功"),
        @ApiResponse(code = 400, message = "更新失败")
    })
    @GlobalInterceptor(checkAdmin = true)
    public R<String> updateAllHistoricalScores() {
        
        try {
            log.info("管理员触发更新所有图片历史分数");
            
            // 这里需要先获取所有图片ID，然后批量更新
            // 由于没有直接的获取所有图片ID的方法，这里简化处理
            // 实际实现中应该先查询所有图片ID，然后批量更新
            
            // TODO: 实现获取所有图片ID的逻辑
            // List<Long> allPictureIds = pictureMapper.selectAllPictureIds();
            // int successCount = pictureHotnessService.batchUpdateHistoricalScores(allPictureIds);
            
            log.info("所有图片历史分数更新完成");
            return ok("历史分数更新完成");
            
        } catch (Exception e) {
            log.error("更新所有图片历史分数失败", e);
            return no("历史分数更新失败：" + e.getMessage());
        }
    }
    
    @PostMapping("/ranking/regenerate/all")
    @ApiOperation(value = "重新生成所有排行榜", notes = "管理员手动触发重新生成所有类型的排行榜缓存")
    @ApiResponses({
        @ApiResponse(code = 200, message = "生成成功"),
        @ApiResponse(code = 400, message = "生成失败")
    })
    @GlobalInterceptor(checkAdmin = true)
    public R<String> regenerateAllRankings() {
        
        try {
            log.info("管理员触发重新生成所有排行榜");
            
            // 重新生成所有类型的排行榜
            String[] rankTypes = {"CURRENT", "YESTERDAY", "LAST_WEEK", "LAST_MONTH"};
            int successCount = 0;
            
            for (String rankType : rankTypes) {
                boolean success = rankingCacheService.regenerateRankingCache(rankType);
                if (success) {
                    successCount++;
                }
            }
            
            log.info("排行榜重新生成完成，成功生成: {}/{}", successCount, rankTypes.length);
            return ok("排行榜重新生成完成，成功生成 " + successCount + "/" + rankTypes.length + " 个排行榜");
            
        } catch (Exception e) {
            log.error("重新生成所有排行榜失败", e);
            return no("排行榜重新生成失败：" + e.getMessage());
        }
    }
    
    @GetMapping("/ranking")
    @ApiOperation(value = "获取热度排行榜", notes = "获取指定类型的热度排行榜")
    @ApiResponses({
        @ApiResponse(code = 200, message = "获取成功"),
        @ApiResponse(code = 400, message = "获取失败")
    })
    public R<List<HotnessRankingVO>> getRanking(@ModelAttribute HotnessRankingQueryDTO queryDTO) {
        
        ExHandler.throwIf(queryDTO == null, "查询参数不能为空");
        ExHandler.throwIf(queryDTO.getRankType() == null, "排行类型不能为空");
        
        try {
            log.info("收到排行榜查询请求，类型: {}, 数量: {}", queryDTO.getRankType(), queryDTO.getLimit());
            
            List<HotnessRankingVO> rankingList = rankingCacheService.getRankingList(
                    queryDTO.getRankType(), 
                    queryDTO.getLimit()
            );
            
            return ok(rankingList);
            
        } catch (Exception e) {
            log.error("获取热度排行榜失败", e);
            return no("获取排行榜失败：" + e.getMessage());
        }
    }
    
    @GetMapping("/ranking/current")
    @ApiOperation(value = "获取当前热度排行榜", notes = "获取当前热度排行榜前50名")
    @ApiResponses({
        @ApiResponse(code = 200, message = "获取成功"),
        @ApiResponse(code = 400, message = "获取失败")
    })
    public R<List<HotnessRankingVO>> getCurrentRanking(
            @RequestParam(defaultValue = "50") Integer limit) {
        
        try {
            log.info("收到当前热度排行榜查询请求，数量: {}", limit);
            
            List<HotnessRankingVO> rankingList = rankingCacheService.getRankingList("CURRENT", limit);
            
            return ok(rankingList);
            
        } catch (Exception e) {
            log.error("获取当前热度排行榜失败", e);
            return no("获取当前排行榜失败：" + e.getMessage());
        }
    }
    
    @GetMapping("/ranking/yesterday")
    @ApiOperation(value = "获取昨日热度排行榜", notes = "获取昨日热度排行榜前50名")
    @ApiResponses({
        @ApiResponse(code = 200, message = "获取成功"),
        @ApiResponse(code = 400, message = "获取失败")
    })
    public R<List<HotnessRankingVO>> getYesterdayRanking(
            @RequestParam(defaultValue = "50") Integer limit) {
        
        try {
            log.info("收到昨日热度排行榜查询请求，数量: {}", limit);
            
            List<HotnessRankingVO> rankingList = rankingCacheService.getRankingList("YESTERDAY", limit);
            
            return ok(rankingList);
            
        } catch (Exception e) {
            log.error("获取昨日热度排行榜失败", e);
            return no("获取昨日排行榜失败：" + e.getMessage());
        }
    }
    
    @GetMapping("/ranking/last-week")
    @ApiOperation(value = "获取上周热度排行榜", notes = "获取上周热度排行榜前50名")
    @ApiResponses({
        @ApiResponse(code = 200, message = "获取成功"),
        @ApiResponse(code = 400, message = "获取失败")
    })
    public R<List<HotnessRankingVO>> getLastWeekRanking(
            @RequestParam(defaultValue = "50") Integer limit) {
        
        try {
            log.info("收到上周热度排行榜查询请求，数量: {}", limit);
            
            List<HotnessRankingVO> rankingList = rankingCacheService.getRankingList("LAST_WEEK", limit);
            
            return ok(rankingList);
            
        } catch (Exception e) {
            log.error("获取上周热度排行榜失败", e);
            return no("获取上周排行榜失败：" + e.getMessage());
        }
    }
    
    @GetMapping("/ranking/last-month")
    @ApiOperation(value = "获取上月热度排行榜", notes = "获取上月热度排行榜前50名")
    @ApiResponses({
        @ApiResponse(code = 200, message = "获取成功"),
        @ApiResponse(code = 400, message = "获取失败")
    })
    public R<List<HotnessRankingVO>> getLastMonthRanking(
            @RequestParam(defaultValue = "50") Integer limit) {
        
        try {
            log.info("收到上月热度排行榜查询请求，数量: {}", limit);
            
            List<HotnessRankingVO> rankingList = rankingCacheService.getRankingList("LAST_MONTH", limit);
            
            return ok(rankingList);
            
        } catch (Exception e) {
            log.error("获取上月热度排行榜失败", e);
            return no("获取上月排行榜失败：" + e.getMessage());
        }
    }
    
    @DeleteMapping("/ranking/clear/all")
    @ApiOperation(value = "清除所有排行榜缓存", notes = "管理员手动清除所有类型的排行榜缓存")
    @ApiResponses({
        @ApiResponse(code = 200, message = "清除成功"),
        @ApiResponse(code = 400, message = "清除失败")
    })
    @GlobalInterceptor(checkAdmin = true)
    public R<String> clearAllRankingCache() {
        
        try {
            log.info("管理员触发清除所有排行榜缓存");
            
            boolean success = rankingCacheService.clearAllRankingCache();
            
            if (success) {
                return ok("所有排行榜缓存清除成功");
            } else {
                return no("清除失败");
            }
            
        } catch (Exception e) {
            log.error("清除所有排行榜缓存失败", e);
            return no("清除失败：" + e.getMessage());
        }
    }

    @GetMapping("/strategies")
    @ApiOperation(value = "获取所有热度计算策略", notes = "获取系统中所有可用的热度计算策略")
    @ApiResponses({
        @ApiResponse(code = 200, message = "获取成功"),
        @ApiResponse(code = 400, message = "获取失败")
    })
    public R<List<HotnessStrategyFactory.StrategyInfo>> getAllStrategies() {
        
        try {
            log.info("收到获取策略列表请求");
            
            List<HotnessStrategyFactory.StrategyInfo> strategies = strategyFactory.getAllStrategyNames()
                    .stream()
                    .map(strategyFactory::getStrategyInfo)
                    .collect(Collectors.toList());
            
            return ok(strategies);
            
        } catch (Exception e) {
            log.error("获取策略列表失败", e);
            return no("获取策略列表失败：" + e.getMessage());
        }
    }
    
    @GetMapping("/strategies/enabled")
    @ApiOperation(value = "获取启用的热度计算策略", notes = "获取系统中所有启用的热度计算策略")
    @ApiResponses({
        @ApiResponse(code = 200, message = "获取成功"),
        @ApiResponse(code = 400, message = "获取失败")
    })
    public R<List<String>> getEnabledStrategies() {
        
        try {
            log.info("收到获取启用策略列表请求");
            
            List<String> enabledStrategies = strategyFactory.getEnabledStrategyNames();
            
            return ok(enabledStrategies);
            
        } catch (Exception e) {
            log.error("获取启用策略列表失败", e);
            return no("获取启用策略列表失败：" + e.getMessage());
        }
    }
    
    @GetMapping("/strategies/{strategyName}")
    @ApiOperation(value = "获取策略详情", notes = "获取指定策略的详细信息")
    @ApiResponses({
        @ApiResponse(code = 200, message = "获取成功"),
        @ApiResponse(code = 400, message = "获取失败")
    })
    public R<HotnessStrategyFactory.StrategyInfo> getStrategyInfo(@PathVariable String strategyName) {
        
        ExHandler.throwIf(strategyName == null, "策略名称不能为空");
        
        try {
            log.info("收到获取策略详情请求，策略名称: {}", strategyName);
            
            HotnessStrategyFactory.StrategyInfo strategyInfo = strategyFactory.getStrategyInfo(strategyName);
            
            if (strategyInfo != null) {
                return ok(strategyInfo);
            } else {
                return no("策略不存在");
            }
            
        } catch (Exception e) {
            log.error("获取策略详情失败，策略名称: {}", strategyName, e);
            return no("获取策略详情失败：" + e.getMessage());
        }
    }
} 